package com.samphanie.auiu.library.restful

/**
 * @author Dries
 *
 * 代理CallFactory创建出来的call对象，从而实现拦截器的派发动作
 **/
class Scheduler(
    private val callFactory: AuiuCall.Factory,
    private val interceptors: MutableList<AuiuInterceptor>
) {
    fun newCall(request: AuiuRequest): AuiuCall<*> {
        val newCall: AuiuCall<*> = callFactory.newCall(request)

        return ProxyCall(newCall, request)
    }

    internal inner class ProxyCall<T>(
        private val delegate: AuiuCall<T>,
        private val request: AuiuRequest
    ) : AuiuCall<T> {

        override fun execute(): AuiuResponse<T> {
            dispatchInterceptor(request, null)
            val response = delegate.execute()
            dispatchInterceptor(request, response)
            return response
        }

        override fun enqueue(callback: AuiuCallback<T>) {
            dispatchInterceptor(request, null)
            delegate.enqueue(object : AuiuCallback<T> {
                override fun onSuccess(response: AuiuResponse<T>) {
                    dispatchInterceptor(request, response)
                    callback.onSuccess(response)
                }

                override fun onFailed(throwable: Throwable) {
                    callback.onFailed(throwable)
                }
            })
        }


        private fun dispatchInterceptor(request: AuiuRequest, response: AuiuResponse<T>?) {
            if (interceptors.size <= 0) return
            InterceptorChain(request, response).dispatch()
        }

        internal inner class InterceptorChain(
            private val request: AuiuRequest,
            private val response: AuiuResponse<T>?
        ): AuiuInterceptor.Chain {
            // 分发的第几个拦截器
            var callIndex : Int = 0
            override val isRequestPeriod: Boolean
                get() = response == null

            override fun request(): AuiuRequest {
                return request
            }

            override fun response(): AuiuResponse<*>? {
                return response
            }

            fun dispatch() {
                val interceptor = interceptors[callIndex]
                val intercept = interceptor.intercept(this)
                callIndex++
                if (!intercept && callIndex < interceptors.size) {
                    dispatch()
                }
            }

        }

    }
}